import { PKEffectBlockComponent } from "@/parkour/effectBlocks/effectBlock";
import { insetVolume } from "@/parkour/func";
import { parkourGameModule } from "@/parkour/module";
import { GameMode, Player } from "@minecraft/server";
import { Dimensions } from "@sapi-game/constants";
import { Timer } from "@sapi-game/gameComponent/common/timer/timer";
import { RandomUtils, Vector3Utils } from "@sapi-game/utils";
import { EndPointFinder } from "./components/endPointFinder";
import { PKGameOverController } from "./components/gameOverController";
import { PKItemStoreComponent } from "./components/itemStrore";
import { PKDaemon } from "./components/pkDaemon";
import { PKPlayerSwitcher } from "./components/playerSwitcher";
import { PKParkourConfig } from "./interface";
import { CubeRegion } from "@sapi-game/gameRegion/gameRegion";
import { DimensionIds } from "@sapi-game/utils/vanila-data";

export class PKParkourState extends parkourGameModule.State<PKParkourConfig> {
    get isBlue() {
        return this.config?.team == this.context.blue.team;
    }
    get isTest() {
        return this.config?.isTest;
    }
    get team() {
        return this.config!.team;
    }

    override onEnter(): void {
        if (this.config == undefined) {
            this.popState();
            return;
        }

        //添加finder
        this.addComponent(EndPointFinder);
        const finder = this.getComponent(EndPointFinder);

        this.runner.run(async (r) => {
            const steps = [
                () => this.init(),
                async () => {
                    const searchVolume = insetVolume(this.config!.volume)!;
                    await finder.search(searchVolume);
                },
                () => this.checkStartPoints(),
                () => this.addComponent(PKItemStoreComponent),
                () => this.spawnActivePlayer(),
                () => {
                    this.addComponent(Timer, {
                        initialTime: this.context.config.runTime,
                        compensate: true,
                        autoStart: true,
                    })
                        .addComponent(PKPlayerSwitcher)
                        .addComponent(PKGameOverController)
                        .addComponent(PKDaemon);
                    if (this.context.config.blockEnabled) {
                        this.addComponent(PKEffectBlockComponent);
                    }
                },
            ];
            try {
                await r.runSteps(steps);
            } catch (e) {
                this.logger.error("runner错误", e);
                r.doDelay(() => this.onLose(), 40);
            }
        });
    }

    init() {
        this.context.groupSet.runCommands([
            `title @s subtitle ${this.isBlue ? "§b蓝" : "§c红"}队上场`,
            `title @s title ${this.isTest ? "§e测试" : "跑酷"}阶段`,
            "clear @s",
            "effect @s clear",
        ]);
        const region = new CubeRegion(
            DimensionIds.Overworld,
            this.config!.volume.getMin(),
            this.config!.volume.getMax()
        );
        region
            .getEntitesInRegion({ type: "minecraft:arrow" })
            .forEach((e) => e.remove());
        this.context.groupSet.forEach((p) => {
            if (!p.player) return;
            this.tpToSpawn(p.player);
            p.player.setSpawnPoint({
                ...this.context.spawn,
                dimension: Dimensions.Overworld,
            });
        });
    }

    tpToSpawn(p: Player) {
        const baseLoc = this.config!.baseLocation;
        p.teleport(Vector3Utils.add(baseLoc, this.context.map.spawnPos), {
            dimension: Dimensions.Overworld,
        });
        p.setGameMode(GameMode.Spectator);
    }

    spawnActivePlayer(player?: Player) {
        const endPoints = this.getComponent(EndPointFinder).getPoints();
        if (!player) {
            //未传入则随机选取
            player = this.team.random()?.player;
        }
        const loc = RandomUtils.choice(endPoints);

        if (loc && player) {
            const block = Dimensions.Overworld.getBlock(loc)?.above();
            if (!block) {
                this.context.groupSet.runCommand("title @s title 无法获取起点");
                throw new Error("无法获取起点");
            }
            player.teleport(block.center());

            player.setGameMode(GameMode.Adventure);
            //队伍中其它玩家改旁观
            const ans = this.context.groupSet.findById(player.id);
            ans?.group.forEach((p) => {
                if (p.player != player)
                    p.player?.setGameMode(GameMode.Spectator);
            });
            //加载物品
            const store = this.getComponent(PKItemStoreComponent);
            store.loadItem(player);
        } else {
            this.context.groupSet.runCommand("title @s title 未找到玩家或起点");
            throw new Error("无起点，结束");
        }
    }

    checkStartPoints() {
        const finder = this.getComponent(EndPointFinder);
        const endPoints = finder.getPoints();
        if (endPoints.length == 0) {
            this.context.groupSet.runCommand("title @s title 未找到起点");
            throw new Error("无起点，结束");
        }
    }

    onWin() {
        const timer = this.getComponent(Timer);
        if (this.isBlue) {
            this.context.blue.score += timer.time;
            this.context.groupSet.sendMessage(`§b蓝队得分:${timer.time}`);
        } else {
            this.context.red.score += timer.time;
            this.context.groupSet.sendMessage(`§c红队得分:${timer.time}`);
        }
        this.showScore();
        this.popState();
    }

    onLose() {
        let mes = this.isBlue ? "蓝队失败了,不得分" : "红队失败了,不得分";
        this.context.groupSet.sendMessage(mes);
        this.showScore();
        this.popState();
    }

    /**展示当前得分 */
    showScore() {
        const lines = [
            "---当前分数---",
            `§b蓝队§r:${this.context.blue.score}分`,
            `§c红队§r:${this.context.red.score}分`,
        ];
        this.context.groupSet.sendMessage(lines.join("\n"));
    }
}
